package com.twxm.breed.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.twxm.breed.entity.*;
import com.twxm.breed.iot.ALiYunIOTAPI;
import com.twxm.breed.iot.OxygenTaskManager;
import com.twxm.breed.service.*;
import com.twxm.breed.util.Base64Util;
import com.twxm.breed.util.UploadUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

@RequestMapping("/device")
@RestController
@Slf4j
public class DeviceController {
    @Autowired
    private DeviceInfoService deviceInfoService;
    @Autowired
    private LoginInfoService loginInfoService;
    @Autowired
    private FishPondService fishPondService;
    @Autowired
    private DeviceCateInfoService deviceCateInfoService;
    @Autowired
    private CategoryInfoService categoryInfoService;
    @Autowired
    private DeviceIOTService deviceIOTService;
    @Autowired
    private TimerManager timerManager;
    @Autowired
    private MonitorService monitorService;
    @Autowired
    private WaterFactorService waterFactorService;
    @Autowired
    private WeatherFactorService weatherFactorService;
    @Autowired
    private DissolvedOxygenService dissolvedOxygenService;
    @Autowired
    private EventLogService eventLogService;
    @PostMapping("/add_device")
    public JSONObject addDevice(@RequestParam(value = "userid") String userId,
                                @RequestParam(value = "pondid") String pondId,
                                @RequestParam(value = "deviceid") String deviceId,
                                @RequestParam(value = "devicename") String deviceName,
                                @RequestParam(value = "devicemodel") String deviceModel,
                                @RequestParam(value = "image") MultipartFile file){
        log.info("正在添加设备。。");
        JSONObject jsonObject = new JSONObject();
        if (loginInfoService.getFlag(userId) == null || loginInfoService.getFlag(userId)==0){
            jsonObject.put("res","permissionError");
            return jsonObject;
        }
        String path = UploadUtil.saveFile("device", file,"image");
        if (path == null){
            jsonObject.put("res","non");
            return jsonObject;
        }
        if (path.equals("error")){
            jsonObject.put("res","false");
            return jsonObject;
        }
        CategoryInfo categoryInfo = new CategoryInfo(deviceName,deviceModel);
        if (categoryInfoService.getId(categoryInfo) != null){
            categoryInfo.setCategoryId(categoryInfoService.getId(categoryInfo));
        }
        FishPond pond = fishPondService.selectById(pondId);
        DeviceInfo deviceInfo = new DeviceInfo(deviceId,categoryInfo,pond,path);
        try {
            deviceCateInfoService.insertDevice(categoryInfo, deviceInfo);
            jsonObject.put("res","success");
            return jsonObject;
        } catch (Exception e) {
            e.printStackTrace();
            jsonObject.put("res","false");
            return jsonObject;
        }
    }

    @GetMapping("/get_devices")
    public JSONArray getDevices(){
        JSONArray jsonArray = new JSONArray();
        List<DeviceInfo> list = deviceInfoService.getAll();
        for (DeviceInfo deviceInfo:list){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("deviceid",deviceInfo.getDeviceId());
//            String cateId = deviceInfo.getDeviceId();
//            CategoryInfo categoryInfo = categoryInfoService.getCateById(cateId);
            jsonObject.put("name",deviceInfo.getCategoryInfo().getName());//设备名
            jsonObject.put("model",deviceInfo.getCategoryInfo().getModel());//设备型号
            jsonObject.put("pondid",deviceInfo.getFishPond().getPondId());
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date startTime = deviceInfo.getStartTime();
            String reportDateStr;
            if(startTime == null){
                reportDateStr = "--";
            }else{
                reportDateStr = formatter.format(startTime);
            }
            jsonObject.put("startTime",reportDateStr);
            try {
                jsonObject.put("image", Base64Util.getBase64(deviceInfo.getImage()));
                String status = ALiYunIOTAPI.getInstance().getDeviceStatus(deviceInfo.getCategoryInfo().getProductKey(),deviceInfo.getDeviceId());
                jsonObject.put("status",status);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClientException e) {
                jsonObject.put("status","OFFLINE");
            }
            jsonArray.add(jsonObject);
        }
        return jsonArray;
    }

    @PostMapping("/set_devices")
    public JSONObject setStatus(@RequestParam("deviceid")String deviceId,
                                @RequestParam("status")String status) throws ClientException {
        //1.根据deviceid查productkey
//        CategoryInfo categoryInfo = deviceInfoService.getcategoryInfo(deviceId);
        //2.productkey来查有什么功能
        //3.根据设置频率来设置值
        DeviceInfo deviceInfo = deviceInfoService.selectById(deviceId);
        CategoryInfo categoryInfo = deviceInfo.getCategoryInfo();
        FishPond fishPond = deviceInfo.getFishPond();
        String pondId = fishPond.getPondId();
        JSONObject jsonObject = new JSONObject();
        if (status.equals("OFFLINE")){
            deviceInfoService.setStatusClose(deviceId);
            try {
                // 如果是增氧泵的话，那就关掉任务
                if(categoryInfo.getName().equals("增氧泵")){
                    OxygenTaskManager.getInstance().removePond(pondId);
                }
                ALiYunIOTAPI.getInstance().setDeviceClose(categoryInfo.getProductKey(),deviceId);
                jsonObject.put("res","suc");
            } catch (ClientException e) {
                jsonObject.put("res","false");
            }
            return jsonObject;
        }
        deviceInfoService.setStatusOpen(deviceId);
        ALiYunIOTAPI.getInstance().setDeviceOpen(categoryInfo.getProductKey(), deviceId);
        // 第一次执行的时间戳
        switch (categoryInfo.getName()){
            case "水质化学传感器":
                timerManager.removeTask(pondId);
                timerManager.addTask(fishPond, 5000, deviceInfo.getMinute()* 60000L);
                jsonObject.put("res","suc");
                return jsonObject;
            case "气象传感器":
                timerManager.removeTask(pondId);
                timerManager.addTask(fishPond, 5000, deviceInfo.getMinute()* 60000L);
                jsonObject.put("res","suc");
                return jsonObject;
            case "水质溶解氧传感器":
                //录入数据库
                timerManager.removeTask(pondId);
                timerManager.addTask(fishPond, 5000, deviceInfo.getMinute()* 60000L);
                jsonObject.put("res","suc");
                return jsonObject;
            case "水泵":
                jsonObject.put("res","suc");
                return jsonObject;
            case "增氧泵":
                //根据鱼塘获取到溶解氧传感器设备，查看是否有设备
                DeviceInfo oxygenDevice = deviceInfoService.getOxygenSensorByPondId(deviceInfo.getFishPond().getPondId());
                //没有设备则告诉前端没有溶解氧传感器
                if (oxygenDevice == null){
                    jsonObject.put("res","noDevice");
                    return jsonObject;
                }
                //判断溶解氧传感器设备是否开了
                if("OFFLINE".equals(ALiYunIOTAPI.getInstance().getDeviceStatus(oxygenDevice.getCategoryInfo().getProductKey(), oxygenDevice.getDeviceId()))){
                    jsonObject.put("res", "close");
                    return jsonObject;
                }

                //搜索monitor
                Monitor monitor = monitorService.getMonitorDeviceId(oxygenDevice.getDeviceId());
                if (monitor == null){
                    jsonObject.put("res","noMonitor");
                    return jsonObject;
                }
                //获取monitor中溶解氧的上下限
                float upper = monitor.getUpper();
                float lower = monitor.getLower();
                OxygenTaskManager.getInstance().addPond(pondId, oxygenDevice, deviceInfo, upper, lower);
                return jsonObject;

        }
        return jsonObject;
    }


    @SneakyThrows
    @PostMapping("/set_oxygenData")
    public JSONObject setOxygenUpperAndLower(@RequestParam ("pondid") String pondId,
                                             @RequestParam("upper") Float upper,
                                             @RequestParam("lower") Float lower){
        //根据pondId找到溶解氧传感器的deviceId
        //如果找不到设备需要告诉前端没有溶解氧传感器，设置失败
        //如果有设备，那么将溶解氧上下限插入到monitor中.
        //每一次插入都不需要覆盖原来的数据
        //Task变更
       JSONObject jsonObject = new JSONObject();
       DeviceInfo deviceInfo = deviceInfoService.getOxygenSensorByPondId(pondId);
       if (deviceInfo == null){
           jsonObject.put("res",500);
           return jsonObject;
       }
        Monitor monitor = new Monitor(deviceInfo,upper,lower,new Date());
        monitorService.setMonitor(monitor);
        //如果设备开启了，任务变更
        if (deviceInfo.getStatus()==1|| ALiYunIOTAPI.getInstance().getDeviceStatus(deviceInfo.getCategoryInfo().getProductKey(),deviceInfo.getDeviceId()).equals("ONLINE")){
            // 更新上下限
            if(!OxygenTaskManager.getInstance().changeUpperAndLower(pondId, upper, lower)){
                jsonObject.put("res",202);
            }else{
                jsonObject.put("res",200);
            }
        }else{
            jsonObject.put("res",202);
        }
        return jsonObject;
    }

    @PostMapping("/search_device")
    public JSONObject searchDeviceId(@RequestParam("deviceid") String deviceId){
        JSONObject jsonObject = new JSONObject();
        if (deviceInfoService.selectById(deviceId)==null){
            jsonObject.put("res","false");
            return jsonObject;
        }
        jsonObject.put("res","true");
        return jsonObject;
    }

    @PostMapping("/delete_devices")
    public JSONObject deleteDevices(@RequestBody MyData data){
        JSONObject jsonObject = new JSONObject();
        List<String> list = data.getArray();
        //for (String s:list) {
//            DeviceInfo deviceInfo = deviceInfoService.selectById(s);
//            String productKey = deviceInfo.getCategoryInfo().getProductKey();
//            try {
//                if (!GetDeviceStatusByApi.deleteDevice(productKey, deviceInfo.getDeviceId()) ||
//                        deviceInfoService.deleteDevice(deviceInfo.getDeviceId()) == 0) {
//                    jsonObject.put("res", 500);
//                    return jsonObject;
//                }
//            } catch (ClientException e) {
//                jsonObject.put("res", 400);
//                return jsonObject;
//            }
            try {
                deviceInfoService.deleteDevices(list);
                jsonObject.put("res",200);
            } catch (ClientException e) {
                jsonObject.put("res",400);
            }
        //}
        return jsonObject;
    }

    @PostMapping("/set_collectionTime")
    public JSONObject setCollectionTime(@RequestParam("pondid")String pondId,
                                        @RequestParam("minutes")int minutes){
        FishPond fishPond = fishPondService.selectById(pondId);
        JSONObject jsonObject = new JSONObject();
        if(fishPond == null){
            jsonObject.put("res",400);
            return jsonObject;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("pondId", pondId);
        map.put("minutes",minutes);
        deviceInfoService.setMinutes(map);
        jsonObject.put("res",200);
        timerManager.removeTask(pondId);
        timerManager.addTask(fishPond, 5000, minutes * 60000L);
        return jsonObject;
    }

    @GetMapping("/get_alert")
    public JSONArray getAlert(){
        JSONArray jsonArray = new JSONArray();
        List<EventLog> list = eventLogService.getAll();
        list.forEach(eventLog -> {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("pondid",eventLog.getPond().getPondId());
            jsonObject.put("low",eventLog.getLower());
            jsonObject.put("high",eventLog.getUpper());
            jsonObject.put("Dovalue",eventLog.getOxygen());
            Date date = eventLog.getAlarmTime();
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String reportDateStr = formatter.format(date);
            jsonObject.put("alarmTime",reportDateStr);
            jsonArray.add(jsonObject);
        });
        return jsonArray;
    }
}


class MyData {
    private List<String> array;

    public List<String> getArray() {
        return array;
    }

    public void setArray(List<String> array) {
        this.array = array;
    }
}